home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Found / FWCollec / PRList.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  16.8 KB  |  583 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                PRList.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFound.hpp"
  11.  
  12. #ifndef PRLIST_H
  13. #include "PRList.h"
  14. #endif
  15.  
  16. #ifndef FWDEBUG_H
  17. #include "FWDebug.h"
  18. #endif
  19.  
  20. #ifdef FW_BUILD_MAC
  21. #include <Errors.h>
  22. #endif
  23.  
  24. //========================================================================================
  25. // FW_CPrivLink
  26. //========================================================================================
  27.  
  28. #ifdef FW_BUILD_MAC
  29. #pragma segment fwcollec
  30. #endif
  31.  
  32. //========================================================================================
  33. // FW_CPrivLink
  34. //========================================================================================
  35. // Many of the simple link methods are inlines; see PRList.h for implementations.
  36.  
  37. //----------------------------------------------------------------------------------------
  38. // FW_CPrivLink::FW_CPrivLink
  39. //----------------------------------------------------------------------------------------
  40. // Constructor for FW_CPrivLink
  41.  
  42. FW_CPrivLink::FW_CPrivLink() :
  43.     fNext(NULL), 
  44.     fPrevious(NULL)                    
  45. }
  46.  
  47. //----------------------------------------------------------------------------------------
  48. // FW_CPrivLink::FW_CPrivLink
  49. //----------------------------------------------------------------------------------------
  50. // Constructor for FW_CPrivLink
  51.  
  52. FW_CPrivLink::FW_CPrivLink(FW_CPrivLink* next, FW_CPrivLink* previous) :                        
  53.     fNext(next),
  54.     fPrevious(previous)
  55. }
  56.  
  57. //----------------------------------------------------------------------------------------
  58. // FW_CPrivLink::FW_CPrivLink
  59. //----------------------------------------------------------------------------------------
  60. // Copy constructor for FW_CPrivLink
  61.  
  62. FW_CPrivLink::FW_CPrivLink(const FW_CPrivLink &link) :                            
  63.     fNext(link.fNext), 
  64.     fPrevious(link.fPrevious)
  65. }
  66.  
  67. //----------------------------------------------------------------------------------------
  68. // FW_CPrivLink::FW_CPrivLink
  69. //----------------------------------------------------------------------------------------
  70. // Destructor for FW_CPrivLink
  71.  
  72. FW_CPrivLink::~FW_CPrivLink()                                            
  73. {
  74. }
  75.  
  76. //----------------------------------------------------------------------------------------
  77. // FW_CPrivLink::Remove
  78. //----------------------------------------------------------------------------------------
  79. // Remove a link from its list (if any). DO NOT call this directly if there are
  80. // any iterators active on the list; use FW_CPrivLinkedList::Remove instead.
  81.  
  82. void    FW_CPrivLink::Remove( )
  83. {
  84.     if( fPrevious )
  85.         fPrevious->SetNext(fNext);
  86.     if( fNext )
  87.         fNext->SetPrevious(fPrevious);
  88.     fNext = NULL;
  89.     fPrevious = NULL;
  90. }
  91.  
  92. //----------------------------------------------------------------------------------------
  93. // FW_CPrivLink::AddBefore
  94. //----------------------------------------------------------------------------------------
  95. // Add a link to a list before another link. It must not already be on any list.
  96. // DO NOT call this directly if there are any iterators active on the list;
  97. // use FW_CPrivLinkedList::Remove instead.
  98.  
  99. void    FW_CPrivLink::AddBefore( FW_CPrivLink *link )
  100. {
  101.     FW_ASSERT(link!=NULL);
  102.     FW_ASSERT(fNext==NULL);
  103.     FW_ASSERT(fPrevious==NULL);
  104.     fNext = link;
  105.     fPrevious = link->GetPrevious();
  106.     fPrevious->SetNext(this);
  107.     fNext->SetPrevious(this);
  108. }
  109.  
  110. //----------------------------------------------------------------------------------------
  111. // FW_CPrivLink::AddAfter
  112. //
  113. // Add a link to a list after another link. It must not already be on any list.
  114. // DO NOT call this directly if there are any iterators active on the list;
  115. // use FW_CPrivLinkedList::Remove instead.
  116. //----------------------------------------------------------------------------------------
  117.  
  118. void    FW_CPrivLink::AddAfter( FW_CPrivLink *link )
  119. {
  120.     FW_ASSERT(link!=NULL);
  121.     FW_ASSERT(fNext==NULL);
  122.     FW_ASSERT(fPrevious==NULL);
  123.     fPrevious = link;
  124.     fNext = link->GetNext();
  125.     fPrevious->SetNext(this);
  126.     fNext->SetPrevious(this);
  127. }
  128.  
  129. //========================================================================================
  130. // Class FW_CPrivLinkedList
  131. //========================================================================================
  132.  
  133. //----------------------------------------------------------------------------------------
  134. // FW_CPrivLinkedList::FW_CPrivLinkedList
  135. //----------------------------------------------------------------------------------------
  136. // Constructor for FW_CPrivLinkedList
  137.  
  138. FW_CPrivLinkedList::FW_CPrivLinkedList()
  139.     :fSentinel(&fSentinel,&fSentinel),
  140.      fSeed(0),
  141.      fCount(0)
  142. {
  143. }
  144.  
  145. //----------------------------------------------------------------------------------------
  146. // FW_CPrivLinkedList::~FW_CPrivLinkedList
  147. //----------------------------------------------------------------------------------------
  148. // Destructor for FW_CPrivLinkedList
  149.  
  150. FW_CPrivLinkedList::~FW_CPrivLinkedList()
  151. {
  152.     // The list does NOT delete all its links!
  153. }
  154.  
  155. //----------------------------------------------------------------------------------------
  156. // FW_CPrivLinkedList::IsEmpty
  157. //----------------------------------------------------------------------------------------
  158.  
  159. FW_Boolean FW_CPrivLinkedList::IsEmpty() const
  160. {
  161.     return this->IsSentinel( fSentinel.GetNext() );
  162. }
  163.  
  164. //----------------------------------------------------------------------------------------
  165. // FW_CPrivLinkedList::Count
  166. //----------------------------------------------------------------------------------------
  167.  
  168. unsigned long FW_CPrivLinkedList::Count() const
  169. {
  170.     return fCount;
  171. /*
  172.     FW_CPrivLink* l = fSentinel.GetNext();
  173.     unsigned long count = 0;
  174.     while (this->NotSentinel(l))
  175.     {
  176.         count++;
  177.         l = l->GetNext();
  178.     }
  179.     return count;
  180. */
  181. }
  182.  
  183. //----------------------------------------------------------------------------------------
  184. // FW_CPrivLinkedList::Includes
  185. //----------------------------------------------------------------------------------------
  186. // Does the list include a particular link?
  187.  
  188. FW_Boolean FW_CPrivLinkedList::Includes( const FW_CPrivLink *link ) const
  189. {
  190.     FW_CPrivLink* l = fSentinel.GetNext();
  191.     while (this->NotSentinel(l))
  192.     {
  193.         if( l == link )
  194.             return TRUE;
  195.         else
  196.             l = l->GetNext();
  197.     }
  198.     return FALSE;
  199. }
  200.  
  201. //----------------------------------------------------------------------------------------
  202. // FW_CPrivLinkedList::DeleteAllLinks
  203. //----------------------------------------------------------------------------------------
  204.  
  205. void FW_CPrivLinkedList::DeleteAllLinks()
  206. {
  207.  
  208.     FW_CPrivLink* l = fSentinel.GetNext();
  209.     FW_CPrivLink* n = l;
  210.     while (this->NotSentinel(n))
  211.     {
  212.         n = l->GetNext();
  213.         delete l;    
  214.         l = n;
  215.     }
  216.     fSentinel.SetNext(&fSentinel);
  217.     fSentinel.SetPrevious(&fSentinel);
  218.     fSeed++;
  219.     fCount = 0;
  220. }
  221.  
  222. //----------------------------------------------------------------------------------------
  223. // FW_CPrivLinkedList::RemoveAll
  224. //----------------------------------------------------------------------------------------
  225.  
  226. void FW_CPrivLinkedList::RemoveAll()
  227. {
  228.     FW_CPrivLink* l = fSentinel.GetNext();
  229.     FW_CPrivLink* n = l;
  230.     while (this->NotSentinel(l))
  231.     {
  232.         n = l->GetNext();
  233.         l->SetNext(NULL);
  234.         l->SetPrevious(NULL);
  235.         l = n;
  236.     }
  237.     fSentinel.SetNext(&fSentinel);
  238.     fSentinel.SetPrevious(&fSentinel);
  239.     fSeed++;
  240.     fCount = 0;
  241. }
  242.  
  243. //----------------------------------------------------------------------------------------
  244. // FW_CPrivLinkedList::Remove
  245. //----------------------------------------------------------------------------------------
  246.  
  247. void FW_CPrivLinkedList::Remove(FW_CPrivLink* aLink)
  248. {
  249.     fSeed++;
  250.     fCount--;
  251.     aLink->Remove();
  252. }
  253.  
  254. //----------------------------------------------------------------------------------------
  255. // FW_CPrivLinkedList::RemoveFirst
  256. //----------------------------------------------------------------------------------------
  257.  
  258. FW_CPrivLink* FW_CPrivLinkedList::RemoveFirst()
  259. {
  260.     FW_CPrivLink* old = fSentinel.GetNext();
  261.     if (this->NotSentinel(old))
  262.     {
  263.         fSeed++;
  264.         fCount--;
  265.         old->Remove();
  266.         return old;
  267.     }
  268.     else
  269.     {
  270.         return NULL;
  271.     }
  272. }
  273.  
  274. //----------------------------------------------------------------------------------------
  275. // FW_CPrivLinkedList::RemoveLast
  276. //----------------------------------------------------------------------------------------
  277.  
  278. FW_CPrivLink* FW_CPrivLinkedList::RemoveLast()
  279. {
  280.     FW_CPrivLink* old = fSentinel.GetPrevious();
  281.     if (this->NotSentinel(old))
  282.     {
  283.         fSeed++;
  284.         fCount--;
  285.         old->Remove();
  286.         return old;
  287.     }
  288.     else
  289.     {
  290.         return NULL;
  291.     }
  292. }
  293.  
  294. //----------------------------------------------------------------------------------------
  295. // FW_CPrivLinkedList::AddFirst
  296. //----------------------------------------------------------------------------------------
  297.  
  298. void FW_CPrivLinkedList::AddFirst(FW_CPrivLink* link)
  299. {
  300.     link->AddAfter(this->GetSentinel());
  301.     fSeed++;
  302.     fCount++;
  303. }
  304.  
  305. //----------------------------------------------------------------------------------------
  306. // FW_CPrivLinkedList::AddLast( FW_CPrivLink )
  307. //----------------------------------------------------------------------------------------
  308.  
  309. void FW_CPrivLinkedList::AddLast(FW_CPrivLink* link)
  310. {
  311.     link->AddBefore(this->GetSentinel());
  312.     fSeed++;
  313.     fCount++;
  314. }
  315.  
  316. //----------------------------------------------------------------------------------------
  317. // FW_CPrivLinkedList::AddLast( FW_CPrivLinkedList )
  318. //----------------------------------------------------------------------------------------
  319. // Append contents of another list to my end. (Other list becomes empty.)
  320.  
  321. void FW_CPrivLinkedList::AddLast(FW_CPrivLinkedList &list)
  322. {
  323.     if( !list.IsEmpty() ) {
  324.         FW_CPrivLink *myLast = fSentinel.GetPrevious();
  325.         FW_CPrivLink *itsFirst = list.First();
  326.         myLast->SetNext(itsFirst);
  327.         itsFirst->SetPrevious(myLast);
  328.         
  329.         FW_CPrivLink *itsLast = list.Last();
  330.         itsLast->SetNext(this->GetSentinel());
  331.         fSentinel.SetPrevious(itsLast);
  332.         
  333.         list.fSentinel.SetNext(this->GetSentinel());
  334.         list.fSentinel.SetPrevious(this->GetSentinel());
  335.  
  336.         fSeed++;
  337.         fCount++;
  338.         list.fSeed++;
  339.     }
  340. }
  341.  
  342. //----------------------------------------------------------------------------------------
  343. // FW_CPrivLinkedList::AddLastUnique( FW_CPrivLinkedList )
  344. //----------------------------------------------------------------------------------------
  345. // Append contents of another list (w/o duplication) to my end.
  346.  
  347. void    FW_CPrivLinkedList::AddLastUnique(FW_CPrivLinkedList &list)
  348. {
  349.     for( FW_CPrivLink *link = fSentinel.GetNext(); this->NotSentinel(link); link=link->GetNext() )
  350.         if( list.Includes(link) )
  351.             list.Remove(link);
  352.     this->AddLast(list);
  353. }
  354.  
  355. //----------------------------------------------------------------------------------------
  356. // FW_CPrivLinkedList::AddBefore
  357. //----------------------------------------------------------------------------------------
  358.  
  359. void FW_CPrivLinkedList::AddBefore(FW_CPrivLink* existing, FW_CPrivLink* link)
  360. {
  361.     link->AddBefore(existing);
  362.     fSeed++;
  363.     fCount++;
  364. }
  365.  
  366. //----------------------------------------------------------------------------------------
  367. // FW_CPrivLinkedList::AddAfter
  368. //----------------------------------------------------------------------------------------
  369.  
  370. void FW_CPrivLinkedList::AddAfter(FW_CPrivLink* existing, FW_CPrivLink* link)
  371. {
  372.     link->AddAfter(existing);
  373.     fSeed++;
  374.     fCount++;
  375. }
  376.  
  377. //----------------------------------------------------------------------------------------
  378. // FW_CPrivLinkedList::After
  379. //----------------------------------------------------------------------------------------
  380.  
  381. FW_CPrivLink* FW_CPrivLinkedList::After(const FW_CPrivLink* link) const
  382. {
  383.     FW_CPrivLink *next = link->GetNext();
  384.     return (this->IsSentinel(next)) ? NULL : next;
  385. }
  386.  
  387. //----------------------------------------------------------------------------------------
  388. // FW_CPrivLinkedList::Before
  389. //----------------------------------------------------------------------------------------
  390.  
  391. FW_CPrivLink* FW_CPrivLinkedList::Before(const FW_CPrivLink* link) const
  392. {
  393.     FW_CPrivLink *prev = link->GetPrevious();
  394.     return this->IsSentinel(prev) ? NULL : prev;
  395. }
  396.  
  397. //----------------------------------------------------------------------------------------
  398. // FW_CPrivLinkedList::First
  399. //----------------------------------------------------------------------------------------
  400.  
  401. FW_CPrivLink* FW_CPrivLinkedList::First()  const
  402. {
  403.     return this->NotSentinel(fSentinel.GetNext()) ? fSentinel.GetNext() : (FW_CPrivLink*) NULL;
  404. }
  405.  
  406. //----------------------------------------------------------------------------------------
  407. // FW_CPrivLinkedList::Last
  408. //----------------------------------------------------------------------------------------
  409.  
  410. FW_CPrivLink* FW_CPrivLinkedList::Last() const
  411. {
  412.     return this->NotSentinel(fSentinel.GetPrevious()) ? fSentinel.GetPrevious() : (FW_CPrivLink*) NULL;
  413. }
  414.  
  415. //========================================================================================
  416. // Class FW_CPrivLinkedListIterator
  417. //========================================================================================
  418.  
  419. //----------------------------------------------------------------------------------------
  420. // FW_CPrivLinkedListIterator::FW_CPrivLinkedListIterator
  421. //----------------------------------------------------------------------------------------
  422. // Constructor for FW_CPrivLinkedListIterator
  423.  
  424. FW_CPrivLinkedListIterator::FW_CPrivLinkedListIterator(FW_CPrivLinkedList* list) :
  425.     fList(list),
  426.     fCurrent(NULL),
  427.     fNext(NULL),
  428.     fPrevious(NULL),
  429.     fSentinel(list ? &list->fSentinel : NULL),
  430.     fSeed(list ? fList->fSeed : 0)
  431. {
  432. }
  433.  
  434. //----------------------------------------------------------------------------------------
  435. // FW_CPrivLinkedListIterator::~FW_CPrivLinkedListIterator
  436. //----------------------------------------------------------------------------------------
  437. // Destructor for FW_CPrivLinkedListIterator
  438.  
  439. FW_CPrivLinkedListIterator::~FW_CPrivLinkedListIterator()
  440. {
  441. }
  442.  
  443. //----------------------------------------------------------------------------------------
  444. // FW_CPrivLinkedListIterator::First
  445. //----------------------------------------------------------------------------------------
  446.  
  447. FW_CPrivLink* FW_CPrivLinkedListIterator::First()
  448. {
  449.     if (fList == NULL)
  450.         return NULL;
  451.         
  452.     FW_ASSERT(fSeed == fList->fSeed);
  453.         
  454.     fCurrent = fList->First();
  455.     if (fCurrent == fSentinel)
  456.         fCurrent = NULL;
  457.     return fCurrent;
  458. }
  459.  
  460. //----------------------------------------------------------------------------------------
  461. // FW_CPrivLinkedListIterator::Next
  462. //----------------------------------------------------------------------------------------
  463.  
  464. FW_CPrivLink* FW_CPrivLinkedListIterator::Next()
  465. {
  466.     if (fList == NULL)
  467.         return NULL;
  468.  
  469.     FW_ASSERT(fSeed == fList->fSeed);
  470.  
  471.     if (fCurrent == NULL)
  472.     {
  473.         if ((fNext == NULL) && (fPrevious == NULL))    // Just starting out
  474.         {
  475.             return this->First();
  476.         }
  477.         else    // Just deleted
  478.         {
  479.             fCurrent = fNext;
  480.             fPrevious = NULL;
  481.             fNext = NULL;
  482.         }
  483.     }
  484.     else
  485.         fCurrent = fCurrent->GetNext();
  486.     
  487.     if (fCurrent == fSentinel)
  488.         fCurrent = NULL;
  489.     return fCurrent;
  490. }
  491.  
  492. //----------------------------------------------------------------------------------------
  493. // FW_CPrivLinkedListIterator::Last
  494. //----------------------------------------------------------------------------------------
  495.  
  496. FW_CPrivLink* FW_CPrivLinkedListIterator::Last()
  497. {
  498.     if (fList == NULL)
  499.         return NULL;
  500.  
  501.     FW_ASSERT(fSeed == fList->fSeed);
  502.  
  503.     fCurrent = fList->Last();
  504.     if (fCurrent == fSentinel)
  505.         fCurrent = NULL;
  506.     return fCurrent;
  507. }
  508.  
  509. //----------------------------------------------------------------------------------------
  510. // FW_CPrivLinkedListIterator::Previous
  511. //----------------------------------------------------------------------------------------
  512.  
  513. FW_CPrivLink* FW_CPrivLinkedListIterator::Previous()
  514. {
  515.     if (fList == NULL)
  516.         return NULL;
  517.  
  518.     FW_ASSERT(fSeed == fList->fSeed);
  519.  
  520.     if (fCurrent == NULL)
  521.     {
  522.         if ((fNext == NULL) && (fPrevious == NULL))    // Just starting out
  523.         {
  524.             return this->Last();
  525.         }
  526.         else    // Just deleted
  527.         {
  528.             fCurrent = fPrevious;
  529.             fPrevious = NULL;
  530.             fNext = NULL;
  531.         }
  532.     }
  533.     else
  534.         fCurrent = fCurrent->GetPrevious();
  535.  
  536.     if (fCurrent == fSentinel)
  537.         fCurrent = NULL;
  538.     return fCurrent;
  539. }
  540.  
  541. //----------------------------------------------------------------------------------------
  542. // FW_CPrivLinkedListIterator::Current
  543. //----------------------------------------------------------------------------------------
  544.  
  545. FW_CPrivLink* FW_CPrivLinkedListIterator::Current()
  546. {
  547.     return fCurrent;
  548. }
  549.  
  550. //----------------------------------------------------------------------------------------
  551. // FW_CPrivLinkedListIterator::IsNotComplete
  552. //----------------------------------------------------------------------------------------
  553.  
  554. FW_Boolean FW_CPrivLinkedListIterator::IsNotComplete()
  555. {
  556.     return (fCurrent != NULL);
  557. }
  558.  
  559. //----------------------------------------------------------------------------------------
  560. // FW_CPrivLinkedListIterator::RemoveCurrent
  561. //----------------------------------------------------------------------------------------
  562.  
  563. void  FW_CPrivLinkedListIterator::RemoveCurrent()
  564. {
  565.     if (fList == NULL)
  566.         return;
  567.  
  568.     FW_ASSERT(fSeed == fList->fSeed);
  569.          
  570.     if (fCurrent != NULL)
  571.     {
  572.         fNext = fCurrent->GetNext();
  573.         fPrevious = fCurrent->GetPrevious();
  574.             
  575.         fList->Remove(fCurrent);
  576.         fCurrent = NULL;
  577.         fSeed = fList->fSeed;
  578.     }
  579. }
  580.